package org.twnmayberry.ejb;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.twndmv.dto.PersonDTO;
import org.twndmv.ejb.DmvTestUtilRemote;
import org.twndmv.ejb.PersonMgmtRemote;
import org.twnmayberry.bl.PoiMgmt;
import org.twnmayberry.blimpl.PoiMgmtImpl;
import org.twnmayberry.bo.POI;
import org.twnmayberry.bo.Sex;
import org.twnmayberry.bo.Type;
import org.twnmayberry.dao.POIDAO;
import org.twnmayberry.dto.ActivityDTO;
import org.twnmayberry.dto.DTOUtils;
import org.twnmayberry.dto.POIDTO;
import org.twnmayberry.jpa.POIDAOImpl;

@Stateless
public class PoiMgmtEJB implements PoiMgmtRemote {

	private static Log log = LogFactory.getLog(PoiMgmtEJB.class);
	
	@PersistenceContext(unitName = "mayberryEntity")
	private EntityManager em;
	
	private PoiMgmt poiManager;
	
	@EJB(lookup="ejb:twnDmvEAR/twnDmvEJB/DmvTestUtilEJB!org.twndmv.ejb.DmvTestUtilRemote")
	private DmvTestUtilRemote dmvTestUtil;
	
	@EJB(lookup="ejb:twnDmvEAR/twnDmvEJB/PersonMgmtEJB!org.twndmv.ejb.PersonMgmtRemote")
	private PersonMgmtRemote personManager;
	
	@PostConstruct
	public void init() {
		POIDAO poiDB = new POIDAOImpl(em);
		poiManager = new PoiMgmtImpl(poiDB);
	}
	 
	@Override
	public void addPOI(POIDTO newPOI) {
		poiManager.addPOI(DTOUtils.convertDTOtoPOI(newPOI));
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void addPOIFromDMV(long dmvId) {

		PersonDTO resultPerson = personManager.getPersonByID(dmvId);
	    POIDTO poi = new POIDTO();
	    poi.setFirstName(resultPerson.getFirstName());
	    poi.setMiddleName(resultPerson.getMiddleName());
	    poi.setLastName(resultPerson.getLastName());
	    poi.setGender(Sex.translate(resultPerson.getPhysicalDetails().getSEX().name()));
	    poi.setHeight(resultPerson.getPhysicalDetails().getHeight());
	    poi.setWeight(resultPerson.getPhysicalDetails().getWeight());
	    
	    addPOI(poi);
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void addActivity(long poiID, ActivityDTO newActivity) {
		POI newActDude = poiManager.getPOI(poiID);
		newActDude.getActivities().add(DTOUtils.convertDTOtoActivity(newActivity));
		poiManager.updatePOI(newActDude);
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public POIDTO getPOI(long id) {
		return DTOUtils.convertPOItoDTO(poiManager.getPOI(id));
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public List<POIDTO> getAllPOI() {
        List<POIDTO> results = new ArrayList<POIDTO>();
        
        for(POI dude : poiManager.getAllPOI()) {
        	results.add(DTOUtils.convertPOItoDTO(dude));
        }
        
		return results;
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public boolean isDangerous(POIDTO badGuy) {
       return poiManager.isDangerous(DTOUtils.convertDTOtoPOI(badGuy));
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void populateDB() {
		Random random = new Random();
		for(int i = 0; i < 1000; i++) {
			POIDTO poi = new POIDTO();
			poi.setFirstName("Bob-" + i);
			poi.setMiddleName("Danger-" + i);
			poi.setLastName("Awesome-" + i);
			
			poi.setHeight(random.nextInt(200));
			poi.setWeight(random.nextInt(200));
			ActivityDTO newAct = new ActivityDTO();
			newAct.setDate(new Date(System.currentTimeMillis()));
			newAct.setType(Type.ASSAULT);
			if(i % 67 == 0) {
				newAct.setDescription("This dude is DANGEROUS");
			} else {
				newAct.setDescription("This dude is weak");
			}
		}
		
		dmvTestUtil.populate();
	}

	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public void addList(List<POIDTO> newPeeps) {
		
		for(POIDTO peep : newPeeps) {
		    try {
			poiManager.addPOI(DTOUtils.convertDTOtoPOI(peep));
		    } catch (Exception e) {
		    	log.error("Error adding POI list.  Rolling back the transaction: " + e);
		    	em.getTransaction().rollback();
		    }
		}
		
	}
	
	
}
